<!DOCTYPE html><html lang="zh-cn"><head><meta charset="utf-8"><meta name="X-UA-Compatible" content="IE=edge"><title> Effective JavaScript读书笔记1 · 细雨听风</title><meta name="description" content="Effective JavaScript读书笔记1 - Scott"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="/favicon.png"><link rel="stylesheet" href="/css/apollo.css"><link rel="search" type="application/opensearchdescription+xml" href="http://example.com/atom.xml" title="细雨听风"><meta name="generator" content="Hexo 6.2.0"><link rel="alternate" href="/atom.xml" title="细雨听风" type="application/atom+xml">
</head><body><div class="wrap"><header><a href="/" class="logo-link"><img src="/favicon.png" alt="logo"></a><ul class="nav nav-list"><li class="nav-list-item"><a href="/" target="_self" class="nav-list-link">BLOG</a></li><li class="nav-list-item"><a href="/archives/" target="_self" class="nav-list-link">ARCHIVE</a></li><li class="nav-list-item"><a href="/about" target="_self" class="nav-list-link">ABOUT</a></li></ul></header><main class="container"><div class="post"><article class="post-block"><h1 class="post-title">Effective JavaScript读书笔记1</h1><div class="post-info">2022年7月12日</div><div class="post-content"><p>前几年做iOS的时候，读过Effective OC 2.0，感觉确实很不错，现在做前端开发，想要更深入点学习JavaScript的知识，于是找到了这本Effective JavaScript，好记性不如烂笔头，本系列是用来作读书笔记的。</p>
<h2 id="严格模式"><a href="#严格模式" class="headerlink" title="严格模式"></a>严格模式</h2><p><code>严格模式</code>允许你选择在受限制的JavaScript版本中禁止使用一些JavaScript语言中问题比较多或易于出错的特性。使用严格模式的方式是在程序的最开始增加一个特定的字符串字面量。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&quot;use strict&quot;;</span><br></pre></td></tr></table></figure>

<p>你也可以在函数体的开始处加入这句代码，启用该函数的严格模式。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">function f(x) &#123;</span><br><span class="line">    &quot;use strict&quot;;</span><br><span class="line">    var arguments = []; // error: redefinition of arguments</span><br><span class="line">    // ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><code>use strict</code>只有在脚本或函数的顶部才生效。这样导致非严格模式和严格模式文件之间的导入会出现问题。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">// file1.js</span><br><span class="line">&quot;use strict&quot;;</span><br><span class="line">function f() &#123;</span><br><span class="line">    // ...</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">// file2.js 非严格模式</span><br><span class="line">function g() &#123;</span><br><span class="line">    var arguments = []</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>如果先连接file1再连接file2，那么两个文件都在严格模式下，file2的定义数组变量将会报错，如果先连接file2再连接file1，那么file1将不会在严格模式下运行。</p>
<p>正确的连接方式请看下面代码:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">// file1.js</span><br><span class="line">(function()&#123;</span><br><span class="line">    &quot;use strict&quot;;</span><br><span class="line">    function f() &#123;</span><br><span class="line">        //...</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)();</span><br><span class="line"></span><br><span class="line">// file2.js</span><br><span class="line">(function() &#123;</span><br><span class="line">    function f() &#123;</span><br><span class="line">        var arguments = []</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h2 id="隐式强制转换"><a href="#隐式强制转换" class="headerlink" title="隐式强制转换"></a>隐式强制转换</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">3 + true; // 4</span><br></pre></td></tr></table></figure>

<p>算术运算符-、*、&#x2F;、%在计算之前都会尝试将其参数转换成数字。+ 更为微妙，因为它既重载了数字相加，又重载了字符串连接操作。具体是数字相加还是字符串连接，这取决于其参数的类型。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">2 + 3; // 5</span><br><span class="line">&quot;hello&quot; + &quot;world&quot;; &quot;hello world&quot;;</span><br></pre></td></tr></table></figure>

<p>合并一个数字和字符串时，会将数字转换成字符串：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&quot;2&quot; + 3; // &quot;23&quot;</span><br><span class="line">2 + &quot;3&quot;; // &quot;23&quot;</span><br></pre></td></tr></table></figure>

<p>类似这样的混合表达式有时会令人困惑：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">1 + 2 + &quot;3&quot;; // &quot;33&quot;</span><br><span class="line"></span><br><span class="line">(1 + 2) + &quot;3&quot;; // &quot;33&quot;</span><br><span class="line"></span><br><span class="line">1 + &quot;2&quot; + 3; // &quot;123&quot;</span><br><span class="line"></span><br><span class="line">(1 + &quot;2&quot;) + 3; // &quot;123&quot;</span><br></pre></td></tr></table></figure>

<p>位运算符不仅会将操作数转换为数字，而且还会将操作数转换为32位整数。这些运算符包括位运算(~、 &amp;、^和|)以及移位运算符(&lt;&lt;、&gt;&gt;和&gt;&gt;&gt;)。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&quot;17&quot; * 3; // 51</span><br><span class="line">&quot;8&quot; | &quot;1&quot;; // 9</span><br></pre></td></tr></table></figure>

<p>强制转换也会隐藏错误。 <code>null</code>在算术运算中不会导致失败，而是被隐式地转换为0；一个未定义的变量将被转换为特殊的浮点值NaN。这些强制转换不是立即抛出一个异常，而是继续运算，往往导致一些令人困惑和不可预测的结果。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">var x = NaN;</span><br><span class="line">x === NaN; // false</span><br></pre></td></tr></table></figure>
<p>你可以使用isNaN函数测试它是否是NaN。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">isNaN(NaN); // true;</span><br><span class="line">isNaN(&quot;foo&quot;); // true;</span><br><span class="line">isNaN(undefined); // true;</span><br><span class="line">isNaN(&#123;&#125;); // true</span><br><span class="line">isNaN(&#123;valueOf: &quot;foo&quot;&#125;); // true</span><br></pre></td></tr></table></figure>
<p>有一个简单又可靠的习惯用法来测试NaN。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">var a = NaN;</span><br><span class="line">a !== a; // true</span><br><span class="line"></span><br><span class="line">var b = &quot;foo&quot;;</span><br><span class="line">b !== b; // false</span><br><span class="line"></span><br><span class="line">var c = undefined; </span><br><span class="line">c !== c; // false</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>对象的类型转换</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&quot;J&quot; + &#123;toString: function() &#123;return &quot;S&quot;;&#125;&#125;; // JS</span><br><span class="line">2 * &#123;valueOf: function() &#123;return 3;&#125;&#125; // 6</span><br><span class="line"></span><br><span class="line">var obj = &#123;</span><br><span class="line">    toString: function() &#123;</span><br><span class="line">        return &quot;[object MyObject]&quot;;</span><br><span class="line">    &#125;,</span><br><span class="line">    valueOf: function() &#123;</span><br><span class="line">        return 17;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&quot;object: &quot; + obj; // &quot;object: 17&quot;</span><br></pre></td></tr></table></figure>

<p>真值运算。if、 || 和 &amp;&amp;等运算符逻辑上需要布尔值作为操作参数，但实际上可以接受任何值。大多数的JS值都为真值，也就是能隐式的转换成true。JS中有7个假值：<code>false、0、-0、&quot;&quot;、NaN、null和undefined</code>。其他所有值都为真值。</p>
</div></article></div></main><footer><div class="paginator"><a href="/2022/07/13/Effective-JavaScript%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B02/" class="prev">上一篇</a></div><div class="copyright"><p>© 2015 - 2022 <a href="http://example.com">Scott</a>, powered by <a href="https://hexo.io/" target="_blank">Hexo</a> and <a href="https://github.com/pinggod/hexo-theme-apollo" target="_blank">hexo-theme-apollo</a>.</p></div></footer></div><script async src="//cdn.bootcss.com/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML" integrity="sha384-crwIf/BuaWM9rM65iM+dWFldgQ1Un8jWZMuh3puxb8TOY9+linwLoI7ZHZT+aekW" crossorigin="anonymous"></script></body></html>